package cn.lyjuan.android.demofive.ui.slide.scroll;

import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import cn.lyjuan.android.demofive.R;

/**
 * Created by chad on 2016/4/26.
 */
public class OneLayoutActivity extends Activity implements View.OnTouchListener
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        this.setContentView(R.layout.ui_scroll_one_layout);

        this.initView();

        this.content.setOnTouchListener(this);
        this.menu.setOnTouchListener(this);
    }


    /**
     * 滚动显示和隐藏 menu 时，滑动速度需要达到的最小速度
     **/
    private static final int MIN_VELOCITY = 150;
    /**
     * 屏幕宽度
     **/
    private int screenWidth;
    /**
     * menu最多可以滑动到的左边缘，值由menu布局的宽度来决定，marginLeft到达此值后，不能再减少
     * 最小为负的菜单宽度，下好隐藏菜单
     **/
    private int minLeftMargin;
    /**
     * menu最多可以滑动到的右边缘，值恒为0，即marginLeft到达此值后，不能再增加
     **/
    private static final int maxLeftMargin = 0;
    /**
     * menu给主内容界面保留的宽度
     **/
    private static final int menuHold = 80;
    /**
     * 主内容布局
     **/
    private View content;
    /**
     * menu布局
     **/
    private View menu;
    /**
     * menu布局的参数，通过此参数来更改leftMargin值控制滑动效果
     **/
    private LinearLayout.LayoutParams menuParams;
    /**
     * 记录手指按下的X坐标
     **/
    private float xDown;
    /**
     * 记录手指移动时的X坐标
     **/
    private float xMove;
    /** 上一次移动X坐标 **/
    private float preXMove;
    /**
     * 记录手指抬起时的X坐标
     **/
    private float xUp;
    /**
     * menu当前是显示还是隐藏。只有完全显示或完全隐藏menu时才会更改此值，滑动过程中此值无效
     **/
    private boolean isMenuVisible = false;
    /**
     * 用于计算手指滑动的速度。
     */
    private VelocityTracker velocityTracker;

    private void initView()
    {
        WindowManager win = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
//        this.screenWidth = win.getDefaultDisplay().getSize();
        Point point = new Point();
        win.getDefaultDisplay().getSize(point);
        this.screenWidth = point.x;
        Log.w(OneLayoutActivity.class.getSimpleName(), "screenWidth >> " + this.screenWidth);

        this.content = this.findViewById(R.id.ui_scroll_one_layout_content);
        this.menu = this.findViewById(R.id.ui_scroll_one_layout_menu);

        this.menuParams = (LinearLayout.LayoutParams) menu.getLayoutParams();
        this.menuParams.width = this.screenWidth - this.menuHold;// 将menu的宽度设置为屏幕宽度减去保留的宽度
        this.minLeftMargin = -this.menuParams.width;// 左边缘的值赋值为menu宽度的负数
        this.menuParams.leftMargin = minLeftMargin;// menu的leftMargin设置为左边缘的值，这样初始化时menu就变为不可见
        this.content.getLayoutParams().width = this.screenWidth;// 将content的宽度设置为屏幕宽度
    }

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        createVelocityTracker(event);

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN :// 手指按下
                xDown = event.getRawX();
                preXMove = xDown;
                Log.w(OneLayoutActivity.class.getSimpleName(), "DOWN x >> " + xDown);
                break;

            case MotionEvent.ACTION_MOVE :// 手指拖动
                xMove = event.getRawX();
                Log.w(OneLayoutActivity.class.getSimpleName(), "MOVE x >> " + xMove);

                int disX = (int) (xMove - preXMove);
                int to = menuParams.leftMargin + disX;
                // 防止溢出
                to = to > maxLeftMargin ? maxLeftMargin : to;
                to = to < minLeftMargin ? minLeftMargin : to;

                menuParams.leftMargin = to;
                this.menu.setLayoutParams(menuParams);
                preXMove = xMove;
                break;

            case MotionEvent.ACTION_UP :// 手指抬起
                xUp = event.getRawX();
                if (xDown != xUp)
                {
                    Log.w(OneLayoutActivity.class.getSimpleName(), "UP x >> " + xUp);

                    if (wantShowMenu())// 显示菜单
                        showMenu();
                    else// if (wantShowContent())// 显示主内容
                        showContent();
                }
                recycleVelocityTracker();// 手指抬起后结束追踪器
                break;
        }

        return true;
    }

    private void showMenu()
    {
        new ScrollTask().execute(30);
    }

    private void showContent()
    {
        new ScrollTask().execute(-30);
    }

    /**
     * 当前手势 显示菜单
     *
     * @return 当前手势想显示menu返回true，否则返回false显示主内容。
     */
    private boolean wantShowMenu()
    {
        boolean isToRight = xUp > xDown;
        int disX = (int) Math.abs(xUp - xDown);

        // 向右滑动 且 大于滑动速度
        if (getVeloCity() > MIN_VELOCITY)
            return isToRight;// 当速度大于最低速度时，左滑显示主内容，右滑显示菜单

        // 移动了1/3个菜单宽度
        if (disX > this.menuParams.width / 3) return isToRight;

        // 当前菜单在左半边，隐藏；在右半边显示
        return Math.abs(this.menuParams.leftMargin) < this.menuParams.width / 2;
    }

    /**
     * 获取当前手指滑动X坐标的速度
     * @return
     */
    private int getVeloCity()
    {
        this.velocityTracker.computeCurrentVelocity(1000);// 每秒移动像素

        return Math.abs((int) this.velocityTracker.getXVelocity());
    }

    private void createVelocityTracker(MotionEvent ev)
    {
        if (null == this.velocityTracker)
            this.velocityTracker = VelocityTracker.obtain();

        this.velocityTracker.addMovement(ev);
    }

    private void recycleVelocityTracker()
    {
        this.velocityTracker.recycle();
        this.velocityTracker = null;
    }

    /**
     * 后台显示任务
     */
    class ScrollTask extends AsyncTask<Integer, Integer, Integer>
    {
        @Override
        protected Integer doInBackground(Integer...speed)
        {
            int from = menuParams.leftMargin;
            int leftMargin = menuParams.leftMargin;
            while (true)
            {
                leftMargin += speed[0];// 加上步进
                if (leftMargin > maxLeftMargin)
                {
                    leftMargin = maxLeftMargin;
                    break;
                } else if (leftMargin < minLeftMargin)
                {
                    leftMargin = minLeftMargin;
                    break;
                }

                publishProgress(leftMargin);

                try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
            }

            // 设置菜单是否显示标识
            if (menuParams.leftMargin == maxLeftMargin)
                isMenuVisible = true;
            else if (menuParams.leftMargin == minLeftMargin)
                isMenuVisible = false;

            Log.w(OneLayoutActivity.class.getSimpleName(), "ScrollTask from >> " + from + " to >> " + leftMargin + " isMenu >> " + isMenuVisible);

            return leftMargin;
        }

        @Override
        protected void onProgressUpdate(Integer...leftMargin)
        {
            refreshLeftMargin(leftMargin[0]);
        }

        @Override
        protected void onPostExecute(Integer leftMargin)
        {
            refreshLeftMargin(leftMargin);
        }

        private void refreshLeftMargin(int leftMargin)
        {
            menuParams.leftMargin = leftMargin;
            menu.setLayoutParams(menuParams);
        }
    }
}
